/*******************************************************************************
 * Copyright (c) 2010 European Software Institute - Tecnalia.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Author - Adri�n Noguero (adrian.noguero@esi.es)
 *     
 *******************************************************************************/
package es.esi.gemde.modeltransformator.atlengine;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

/**
 * A dialog to add an input type to a transformation
 *
 * @author Adrian Noguero (adrian.noguero@esi.es)
 * @version 1.0
 * @since 1.0
 *
 */
public class AddTransformationOutputDialog extends Dialog {
	
	private String name;
	private Text mmText;
	private TreeViewer modelViewer;
	private EPackage metamodel = null;
	private EClass eclass = null;
	
	// A Viewer Filter that shows only EClasses
	private ViewerFilter modelFilter = new ViewerFilter() {

		@Override
		public boolean select(Viewer viewer, Object parentElement, Object element) {
			if (element instanceof EClass) {
				return true;
			}
			else
				return false;
		}
		
	};

	// When the select metamodel button is pressed
	private SelectionListener buttonListener = new SelectionListener() {

		@Override
		public void widgetDefaultSelected(SelectionEvent e) {
			// Not needed
		}

		@Override
		public void widgetSelected(SelectionEvent e) {
			// If the button is pressed a new dialog is created to select a metamodel from the registry
			MetamodelSelectionDialog dialog = new MetamodelSelectionDialog(getShell());
			int result = dialog.open();
			if (result == Dialog.OK && dialog.getSelectedMM() != null) {
				mmText.setText(dialog.getSelectedMM().getName() + " : " + dialog.getSelectedMM().getNsURI());
				metamodel = dialog.getSelectedMM();
				modelViewer.setInput(null);
				modelViewer.setInput(metamodel);
				eclass = null;
			}
			updateStatus();
		}
		
	};
	
	private ISelectionChangedListener selectObjectListener = new ISelectionChangedListener() {

		@Override
		public void selectionChanged(SelectionChangedEvent event) {
			Object selection = ((StructuredSelection) modelViewer.getSelection()).getFirstElement();
			if (selection instanceof EClass) {
				if (eclass == null || !eclass.equals(selection) ) {
					eclass = (EClass)selection;
				}
			}
			else {
				eclass = null;
			}
			updateStatus();
		}
	};
	
	
	/**
	 * Constructor of the dialog
	 *
	 *@param parentShell the parent shell
	 */
	public AddTransformationOutputDialog(Shell parentShell) {
		super(parentShell);
		name = new String();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
	 */
	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Add Transformation Output Type");
		newShell.setImage(ATLEngineActivator.getOutputIcon());
		newShell.setSize(400, 400);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
	 */
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		// Only create an OK button
		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
		updateStatus();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		Composite topPanel = (Composite)super.createDialogArea(parent);
		
		GridLayout layout = (GridLayout)topPanel.getLayout();
		layout.numColumns = 6;
		
		Label nameLabel = new Label(topPanel, SWT.NONE);
		GridData nameLabelData = new GridData();
		nameLabelData.horizontalSpan = 2;
		nameLabel.setText("Name:");
		nameLabel.setLayoutData(nameLabelData);
		
		Text nameText = new Text(topPanel, SWT.LEFT | SWT.SINGLE);
		GridData nameTextData = new GridData(GridData.FILL_HORIZONTAL);
		nameTextData.horizontalSpan = 4;
		nameText.setLayoutData(nameTextData);
		nameText.setText(name);
		nameText.addModifyListener(new ModifyListener() {
			
			@Override
			public void modifyText(ModifyEvent e) {
				name = ((Text)e.widget).getText();
			}
		});
		
		Label mmLabel = new Label(topPanel, SWT.NONE);
		GridData mmLabelData = new GridData();
		mmLabelData.horizontalSpan = 1;
		mmLabel.setText("Metamodel:");
		mmLabel.setLayoutData(mmLabelData);
		
		mmText = new Text(topPanel, SWT.LEFT | SWT.SINGLE);
		GridData classTextData = new GridData(GridData.FILL_HORIZONTAL);
		classTextData.horizontalSpan = 4;
		mmText.setLayoutData(classTextData);
		mmText.setEditable(false);
		
		Button browseButton = new Button(topPanel, SWT.PUSH | SWT.CENTER);
		GridData browseButtonData = new GridData();
		browseButtonData.horizontalSpan = 1;
		browseButton.setLayoutData(browseButtonData);
		browseButton.setText("Browse...");
		
		// Create a tree viewer and use EMF edit features to show it!! (taken from PLUM!!)
		modelViewer = new TreeViewer(topPanel, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		GridData modelViewerData = new GridData(GridData.FILL_BOTH);
		modelViewerData.horizontalSpan = 6;
		modelViewer.getTree().setLayoutData(modelViewerData);

		ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
		modelViewer.setContentProvider(new AdapterFactoryContentProvider(adapterFactory));
		modelViewer.setLabelProvider(new AdapterFactoryLabelProvider(adapterFactory));
		modelViewer.addFilter(modelFilter);
		modelViewer.setSorter(new ViewerSorter());
		
		modelViewer.addSelectionChangedListener(selectObjectListener);
		browseButton.addSelectionListener(buttonListener);
		
		if (metamodel != null) {
			mmText.setText(metamodel.getName() + " : " + metamodel.getNsURI());
			modelViewer.setInput(metamodel);
			if (eclass != null) {
				modelViewer.setSelection(new StructuredSelection(eclass));
			}
		}
		
		return topPanel;
	}
	
	/**
	 * Returns the name of the class type
	 * 
	 * @return
	 */
	public String getResult() {
		if (eclass != null) {
			return eclass.getInstanceTypeName();
		}
		else {
			return null;
		}
	}
	
	/**
	 * Returns the selected EClass
	 * 
	 * @return
	 */
	public EClass getEClassResult() {
		return eclass;
	}
	
	/**
	 * Get the name of the output.
	 * 
	 * @return the name of the output
	 */
	public String getOutputName() {
		return name;
	}
	
	/**
	 * Internal method to update the status of the dialog and enable/disable
	 * the OK button.
	 * 
	 */
	private void updateStatus() {
		if (metamodel != null && eclass != null) {
			getButton(IDialogConstants.OK_ID).setEnabled(true);
		}
		else {
			getButton(IDialogConstants.OK_ID).setEnabled(false);
		}
	}
}
